package concurrency.exclusion_mutuelle.v_synchronized;

public class ExclusionMutuelle {
	
	// Cette variable sera accessible par plusieurs processus
	// L'affectation d'un long n'est pas atomique a la difference d'un int, short ... (32 bits)
	private long varPartagee;
	
	public ExclusionMutuelle() {
		varPartagee = 0;
	}
	
	// Tout acces a cette methode se fera en exclusion mutuelle
	// Pour executer la methode il faut disposer du verrou de l'objet courant (this)
	public synchronized void incremente() {
		// Debut SC
		varPartagee++;
		description();
		// Fin SC
	}
	
	public void decremente() {
		synchronized (this) {
			// Debut SC
			varPartagee--;
			description();
			// Fin SC
		}
	}
	
	public void description() {
		String description = Thread.currentThread().getName() + " VAR : " + varPartagee;
		System.out.println(description);
	}
	
	private class Processus implements Runnable {
		
		private Thread thread = new Thread(this);
		private int repetition;
		private boolean incremente;
		
		private Processus(String id, int repetition, boolean incremente) {
			this.incremente = incremente;
			thread.setName(id);
			this.repetition = repetition;
			thread.start();
		}
		
		@Override
		public void run() {
			for (int i = 0; i < repetition; i++) {
				if (incremente) {
					incremente();
				} else {
					decremente();
				}
				Thread.yield();
			}
		}
	}
	
	public static void main(String[] args) {
		ExclusionMutuelle ex = new ExclusionMutuelle();
		Processus p1 = ex.new Processus("Thread_1", 100, true);
		Processus p2 = ex.new Processus("Thread_2", 100, false);
	}
}
